
// JS中相等性判断

// ES6版本 四种相等判断的算法

// 全等 三等 ===
// 等于      ==
// 零值相等  -0 === +0
// 同值相等  -0 !== +0   NaN === NaN

// JS中提供有关相等判断的操作方法

// 严格相等 === Strict Equality
// 非严格(抽象/非约束)相等 == Loose()自由的、不受限制的 Equality(形容说法)
// Object.is(v1, v2) ES6新的API 判断两个参数是否是同一个值

// ---------------------------------------------


// === 严格相等

// 1. 不进行隐式类型转换 - 类型相同/值也相同
// 1 === '1' ? false   1 === 2 ? false

// 2. 引用值必须是同一地址
// var obj = {}   obj === obj ? true    {} === {} ? false (相当于是new Object, 是构造函数)

// 3. 两个NaN 或是 NaN跟其他值 都不相等
// NaN === NaN ? false    NaN === undefined ? false
// 如何定义变量a  a !== a ? true => NaN

// 4. +0 和 -0 相等
// +0 === -0 ? true

// 5. Infinity (无穷/无限)
// + Infinity === - Infinity ? false     Infinity === Infinity ? true


// ---------------------------------------------


// 非严格相等 Abstract equality(描述说法)
// 隐式类型转换 - 等式两边都有可能被转换
// 转换以后还说用严格相等来进行比较

// MDN: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Equality_comparisons_and_sameness
// ToPrimitive(A)通过尝试调用 A 的A.toString() 和 A.valueOf() 方法，将参数 A 转换为原始值（Primitive）

// 任何对象 都与undefined null 不相等
// 窄对象  Narrow Object -> dowcument.all
// document.all == undefined ? true

// 全等对结果的预测是更加清晰明确的
// 全等在不隐式转换的前提下 更快

// falsy值  8个
// false, 0, -0, 8n(bigInt类型), ("", '', ``), null, undefined, NaN


// ---------------------------------------------

// 同值相等 same-value
// 零值相等 same-value-zero  => +0 === -0

// -0 !== +0  => 同值相等的情况下  => 不相等
// NaN === NaN => 同值相等的情况下 => 相等

// var obj = {}
// 在试图修改不可变属性时，如果这个属性确实被修改了则会抛出异常，反之什么都不会发生
// Object.defineProperty(obj, 'myZero', {
//   value: -0,
//   writable: false,
//   enumerable: false,
//   configurable: false
// })

// +0/0 会抛出异常, 不能重新定义myZero 属性 Cannot redefine property: myZero
// Object.defineProperty(obj, 'myZero', {
//   value: -0
// })
// 用Object.defineProperty定义值时 会认为 +0 与 -0 不相等

// Object.defineProperty(obj, 'myNaN', {
//   value: NaN,
//   writable: false,
//   enumerable: false,
//   configurable: false
// })
// Object.defineProperty(obj, 'myNaN', {
//   value: NaN
// })

// 同值相等的底层实现 => Object.is()
// Object.is() ES6抛出来的方法
// ES5并没有暴露JS引擎的同值相等的方法


// ---------------------------------------------


// Object.is() -> ES2015 ES6 -> 同值相等的实现

// var a = 1;
// var b = '1'; // false

// var a = +0;
// var b = -0; // false

// var a = NaN;
// var b = NaN; // true

// var res = Object.is(a, b);
// console.log(res);

// var obj = {};
// 参数就是两个值，返回值就是同值相等判断的bool结果
// const res = Object.is(null, null); // true
// const res = Object.is(obj, obj); // true 同一个引用
// const res = Object.is({}, {}); // false 不同引用值
// console.log(res);

// Object.is() 的判断标准就是同值相等
// 1. -0 !== +0  => 同值相等的情况下  => 不相等 
// 2. NaN === NaN => 同值相等的情况下 => 相等
// 3. 不进行隐式类型转换
// 前两点也是与 全等的区别


// 实现Object.is()

// 1 / -0 -> -Infinity  1 / +0 -> Infinity
// 如何定义变量a  a !== a ? true => NaN

Object.myIs = function(a, b) {
  if (a === b) {
    return a !== 0 || 1 / a === 1 / b
  }

  return a !== a && b !== b
}


// var obj = {};
// const res = Object.myIs(null, null); // true
// const res = Object.myIs(obj, obj); // true 同一个引用
// const res = Object.myIs({}, {}); // false 不同引用值
// const res = Object.myIs(-0, +0); // false
// const res = Object.myIs(NaN, NaN); // true

// console.log(res);


